package com.ecjtu.stadiumre_servations.controller;


import com.ecjtu.stadiumre_servations.service.impl.BookingAnalysisService;
import com.ecjtu.stadiumre_servations.utils.JwtUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@RestController
@RequestMapping("deepSeek")
@Slf4j
public class OpenAIController {
    // 定义问题类型枚举
    public enum QuestionType {
        GENERAL,          // 普通问题
        BOOKING_ANALYSIS, // 预约分析
        BOOKING_CREATE,   // 创建预约
        BOOKING_CANCEL,   // 取消预约
        OTHER
    }
    // 问题意图识别
    private QuestionType identifyQuestionType(String question) {
        if (question.contains("分析") || question.contains("统计") || question.contains("历史")) {
            return QuestionType.BOOKING_ANALYSIS;
        }
        if (question.contains("预约") && (question.contains("创建") || question.contains("新增"))) {
            return QuestionType.BOOKING_CREATE;
        }
        if (question.contains("预约") && (question.contains("取消") || question.contains("删除"))) {
            return QuestionType.BOOKING_CANCEL;
        }
        return QuestionType.GENERAL;
    }

    @Value("${ai.config.deepseek.apiKey}")
    private String API_KEY;

    @Value("${ai.config.deepseek.baseUrl}")
    private String API_URL;

    // 用于保存每个用户的对话历史
    //https://api.deepseek.com/chat/completions 此接口为无状态接口,需要上下文连贯对话需要将历史聊天记录一并发送至接口中
    private final Map<String, List<Map<String, String>>> sessionHistory = new ConcurrentHashMap<>();

    private final ExecutorService executorService = Executors.newCachedThreadPool();
    private final ObjectMapper objectMapper = new ObjectMapper();
    @Autowired
    BookingAnalysisService bookingAnalysisService;
    @GetMapping()
    public ModelAndView chat(ModelAndView modelAndView) {
        modelAndView.setViewName("chat");
        return modelAndView;
    }


    @PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter chat(
//            @RequestHeader("Authorization") String token,
            @RequestBody String question) {

        // 假设 token 是用户的唯一标识
//        String userId = token; // 或者从 token 中解析出用户 ID
//        String userId = "123"; // 或者从 token 中解析出用户 ID
        /*HttpServletRequest request1 = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request1.getHeader("Authorization");
        System.out.println("Token: " + token);
        String userId = JwtUtils.getUsernameFromToken(token);*/
        String userId = "202221100100";


        // 4. 创建SSE发射器，设置超时时间（30分钟）
        SseEmitter emitter = new SseEmitter(-1L);

        // 5. 设置完成、超时和错误处理回调
        emitter.onCompletion(() -> log.info("SSE连接已完成，用户ID: {}", userId));
        emitter.onTimeout(() -> {
            log.warn("SSE连接超时，用户ID: {}", userId);
            emitter.complete();
        });
        emitter.onError(e -> {
            log.error("SSE连接发生错误，用户ID: {}", userId, e);
            emitter.completeWithError(e);
        });

        // 6. 异步处理请求
        executorService.execute(() -> {
            try {
                log.info("流式回答开始, 用户ID: {}, 问题: {}", userId, question);

                // 获取当前用户的对话历史
                List<Map<String, String>> messages = sessionHistory.getOrDefault(userId, new ArrayList<>());

                // 添加用户的新问题到对话历史
                Map<String, String> userMessage = new HashMap<>();
                userMessage.put("role", "user");
                userMessage.put("content", question);
                messages.add(userMessage);

                // 检查问题是否需要预约数据分析
                if (needsBookingAnalysis(question)) {
                    // 执行预约数据分析
                    String analysisResult = bookingAnalysisService.analyzeUserBookingHabit(userId);

                    // 发送分析结果给用户
                    emitter.send(SseEmitter.event()
                            .name("analysis")
                            .data(analysisResult));

                    // 将分析结果添加到对话历史
                    Map<String, String> analysisMessage = new HashMap<>();
                    analysisMessage.put("role", "system");
                    analysisMessage.put("content", "根据您的预约记录分析：\n" + analysisResult);
                    messages.add(analysisMessage);
                }

                // 添加系统消息
                Map<String, String> systemMessage = new HashMap<>();
                systemMessage.put("role", "system");
                systemMessage.put("content", "智慧体育馆预约系统小助手");
                messages.add(systemMessage);

                // 调用 Deepseek API
                try (CloseableHttpClient client = HttpClients.createDefault()) {
                    HttpPost request = new HttpPost(API_URL);
                    request.setHeader("Content-Type", "application/json");
                    request.setHeader("Authorization", "Bearer " + API_KEY);

                    Map<String, Object> requestMap = new HashMap<>();
                    requestMap.put("model", "deepseek-chat");
                    requestMap.put("messages", messages);
                    requestMap.put("stream", true);
                    requestMap.put("temperature", 0.7);
                    requestMap.put("max_tokens", 2000);

                    String requestBody = objectMapper.writeValueAsString(requestMap);
                    request.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));

                    try (CloseableHttpResponse response = client.execute(request);
                         BufferedReader reader = new BufferedReader(
                                 new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8))) {

                        StringBuilder aiResponse = new StringBuilder();
                        String line;

                        // 读取API响应的每一行
                        while ((line = reader.readLine()) != null) {
                            if (line.startsWith("data: ")) {
                                String jsonData = line.substring(6);
                                if ("[DONE]".equals(jsonData)) {
                                    break;
                                }

                                // 解析JSON数据并提取内容
                                JsonNode node = objectMapper.readTree(jsonData);
                                String content = node.path("choices")
                                        .path(0)
                                        .path("delta")
                                        .path("content")
                                        .asText("");

                                if (!content.isEmpty()) {
                                    // 封装成JSON字符串
                                    Map<String, String> msg = new HashMap<>();
                                    msg.put("role", "assistant");
                                    msg.put("content", content);
                                    String jsonMsg = objectMapper.writeValueAsString(msg);

                                    emitter.send(SseEmitter.event()
                                            .name("message")
                                            .data(jsonMsg));
                                    aiResponse.append(content);
                                }
                            }
                        }

                        // 将 AI 的回复添加到对话历史
                        Map<String, String> aiMessage = new HashMap<>();
                        aiMessage.put("role", "assistant");
                        aiMessage.put("content", aiResponse.toString());
                        messages.add(aiMessage);

                        // 更新会话状态
                        sessionHistory.put(userId, messages);

                        log.info("流式回答结束, 用户ID: {}, 问题: {}", userId, question);
                        emitter.complete();
                    }
                } catch (Exception e) {
                    log.error("处理 Deepseek 请求时发生错误，用户ID: {}", userId, e);

                    // 发送错误消息给客户端
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data("抱歉，处理您的请求时发生错误: " + e.getMessage()));

                    emitter.completeWithError(e);
                }
            } catch (Exception e) {
                log.error("处理请求时发生未知错误，用户ID: {}", userId, e);

                try {
                    // 发送通用错误消息给客户端
                    emitter.send(SseEmitter.event()
                            .name("error")
                            .data("抱歉，系统发生了未知错误，请稍后再试。"));
                } catch (Exception ioException) {
                    log.error("发送错误消息失败，用户ID: {}", userId, ioException);
                }

                emitter.completeWithError(e);
            }
        });

        return emitter;
    }

    // 辅助方法：解析Token
    private String parseToken(String authorization) {
        if (authorization == null || !authorization.startsWith("Bearer ")) {
            log.warn("无效的认证格式，期望格式：Bearer {token}");
            return null;
        }
        return authorization.substring(7);
    }

    // 辅助方法：验证Token有效性
    private UserInfo validateToken(String token) {
        try {
            // 实际应用中应通过JWT解析或调用认证服务验证
            io.jsonwebtoken.Claims claims = io.jsonwebtoken.Jwts.parserBuilder()
                    .setSigningKey("sk-1eb5237d124a4f4fbf596df9e14d2215")
                    .build()
                    .parseClaimsJws(token)
                    .getBody();

            String userId = claims.getSubject();

            // 检查Token是否过期
            if (new Date().after(claims.getExpiration())) {
                log.warn("Token已过期，用户ID: {}", userId);
                return null;
            }

            return new UserInfo(userId);

        } catch (io.jsonwebtoken.JwtException | ClassCastException e) {
            log.error("Token验证失败", e);
            return null;
        }
    }

    // 辅助方法：处理无效Token
    private SseEmitter handleInvalidToken() {
        SseEmitter emitter = new SseEmitter(1000L);
        try {
            emitter.send(SseEmitter.event()
                    .name("error")
                    .data("认证失败：无效的Token格式"));
        } catch (Exception e) {
            log.error("发送错误响应失败", e);
        } finally {
            emitter.complete();
        }
        return emitter;
    }

    // 辅助方法：处理过期Token
    private SseEmitter handleExpiredToken() {
        SseEmitter emitter = new SseEmitter(1000L);
        try {
            emitter.send(SseEmitter.event()
                    .name("error")
                    .data("认证失败：Token已过期，请重新登录"));
        } catch (Exception e) {
            log.error("发送错误响应失败", e);
        } finally {
            emitter.complete();
        }
        return emitter;
    }

    // 判断问题是否需要预约数据分析
    private boolean needsBookingAnalysis(String question) {
        List<String> analysisKeywords = Arrays.asList(
                "预约分析", "我的预约", "预约记录", "消费统计",
                "场地使用", "预约习惯", "时段偏好", "预约历史",
                "消费记录", "消费金额", "场地偏好", "最近预约"
        );

        // 检查问题是否包含分析关键词
        return analysisKeywords.stream()
                .anyMatch(question::contains);
    }

    // 用户信息类
    private static class UserInfo {
        private final String userId;

        public UserInfo(String userId) {
            this.userId = userId;
        }

        public String getUserId() {
            return userId;
        }
    }
}